package services;

import java.util.Collection;
import java.util.HashSet;

import javax.transaction.Transactional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import repositories.ComunidadDeVecinosRepository;
import domain.Acta;
import domain.Administrador;
import domain.ComunidadDeVecinos;
import domain.Cuota;
import domain.Incidencia;
import domain.Mensaje;
import domain.MensajeComunidad;
import domain.Pago;
import domain.Presupuesto;
import domain.Reunion;
import domain.Vecino;
import forms.ComunidadDeVecinosForm;

@Service
@Transactional
public class ComunidadDeVecinosService {

	// Managed Repository
	@Autowired
	private ComunidadDeVecinosRepository comunidadDeVecinosRepository;
	// SupportingServices
	@Autowired
	private VecinoService vecinoService;

	@Autowired
	private AdministradorService administradorService;

	@Autowired
	private PresupuestoService presupuestoService;

	@Autowired
	private IncidenciaService incidenciaService;

	@Autowired
	private MensajeComunidadService mensajeComunidadService;

	@Autowired
	private CuotaService cuotaService;

	@Autowired
	private ReunionService reunionService;

	@Autowired
	private ActaService actaService;

	@Autowired
	private MensajeService mensajeService;

	@Autowired
	private PagoService pagoService;

	// Constructors
	public ComunidadDeVecinosService() {
		super();
	}

	// Simple CRUD methods
	public ComunidadDeVecinos findOne(int comunidadDeVecinosId) {
		ComunidadDeVecinos result;

		result = comunidadDeVecinosRepository.findOne(comunidadDeVecinosId);
		Assert.notNull(result);

		return result;
	}

	public Collection<ComunidadDeVecinos> findAll() {
		Collection<ComunidadDeVecinos> res;

		Assert.isTrue(administradorService.findByPrincipal() instanceof Administrador);

		res = comunidadDeVecinosRepository.findAll();

		return res;
	}

	public ComunidadDeVecinos create() {
		ComunidadDeVecinos res;
		Administrador principal;

		res = new ComunidadDeVecinos();
		principal = administradorService.findByPrincipal();
		Assert.isTrue(principal instanceof Administrador);

		res.setActas(new HashSet<Acta>());
		res.setCuotas(new HashSet<Cuota>());
		res.setIncidencias(new HashSet<Incidencia>());
		res.setMensajesComunidad(new HashSet<MensajeComunidad>());
		res.setPagos(new HashSet<Pago>());
		res.setVecinos(new HashSet<Vecino>());
		res.setPresidente(null);
		res.setPresupuesto(null);

		return res;
	}

	public ComunidadDeVecinos save(ComunidadDeVecinos cv) {
		Assert.notNull(cv);
		Administrador principal;
		Assert.notNull(cv.getPresupuesto());
		Assert.isTrue(cv.getPresupuesto().getEstado().equals("Aceptado"));
		principal = administradorService.findByPrincipal();
		Assert.isTrue(principal instanceof Administrador);

		ComunidadDeVecinos res;

		res = comunidadDeVecinosRepository.save(cv);

		return res;
	}

	public void delete(int comunidadId) {
		Administrador principal;
		ComunidadDeVecinos cv;
		Presupuesto presupuesto;
		Collection<Incidencia> incidencias;
		Collection<MensajeComunidad> mensajesComunidad;
		Collection<Cuota> cuotas;
		Collection<Reunion> reuniones;
		Collection<Vecino> vecinos;
		Collection<Acta> actas;
		Collection<Mensaje> mensajes;
		Collection<Pago> pagos;

		cv = comunidadDeVecinosRepository.findOne(comunidadId);
		principal = administradorService.findByPrincipal();
		Assert.isTrue(principal instanceof Administrador);

		pagos = cv.getPagos();
		incidencias = cv.getIncidencias();
		mensajesComunidad = cv.getMensajesComunidad();
		cuotas = cv.getCuotas();
		vecinos = cv.getVecinos();
		reuniones = cv.getReuniones();

		for (Pago p : pagos) {
			if (p.getEstado().equals("No pagado")) {
				Assert.isTrue(!p.getRazonSocial().equals("Asytec"));
			} else {
				pagoService.delete(p);
			}

		}

		for (Incidencia inc : incidencias) {
			for (Presupuesto p : inc.getPresupuestos()) {
				presupuestoService.delete(p);
			}
			incidenciaService.delete(inc);
		}

		for (MensajeComunidad mc : mensajesComunidad) {
			mensajeComunidadService.delete(mc);
		}

		for (Cuota c : cuotas) {
			cuotaService.delete(c);
		}
		for (Reunion r : reuniones) {
			actas = r.getActas();
			for (Acta a : actas) {
				actaService.delete(a);
			}
			reunionService.delete(r);

		}

		for (Vecino v : vecinos) {
			if (v.getComunidadesDeVecinos().size() == 1) {

				mensajes = v.getMensajes();

				for (Mensaje m : mensajes) {
					mensajeService.delete(m);
				}
				vecinoService.delete(v);
			} else {
				Collection<ComunidadDeVecinos> comunidades;
				comunidades = v.getComunidadesDeVecinos();
				comunidades.remove(cv);
				v.setComunidadesDeVecinos(comunidades);
				vecinoService.save(v);
			}
		}

		presupuesto = cv.getPresupuesto();

		comunidadDeVecinosRepository.delete(comunidadId);
		presupuestoService.delete(presupuesto);
	}

	// Other Business methods

	// Form Methods

	public ComunidadDeVecinosForm createForm() {
		ComunidadDeVecinosForm cvForm;

		cvForm = new ComunidadDeVecinosForm();

		cvForm.setComunidadId(0);
		cvForm.setPresupuesto(null);
		cvForm.setFondo(0.0);

		return cvForm;
	}

	public ComunidadDeVecinosForm comunidadToForm(ComunidadDeVecinos cv) {
		Assert.notNull(cv);
		ComunidadDeVecinosForm result;

		result = new ComunidadDeVecinosForm();

		result.setComunidadId(cv.getId());
		result.setPresupuesto(cv.getPresupuesto());

		result.setCif(cv.getCif());
		result.setDireccion(cv.getDireccion());
		result.setNumeroDeCuenta(cv.getNumeroDeCuenta());
		result.setImporteCuota(cv.getImporteCuota());
		result.setFondo(cv.getFondo());

		return result;
	}

	public ComunidadDeVecinos reconstruct(ComunidadDeVecinosForm cvf) {
		Assert.notNull(cvf);
		ComunidadDeVecinos result;
		Assert.isTrue(cvf.getPresupuesto().getEstado().equals("Aceptado"));

		if (cvf.getComunidadId() == 0) {
			result = create();

			result.setCif(cvf.getCif());
			result.setDireccion(cvf.getDireccion());
			result.setNumeroDeCuenta(cvf.getNumeroDeCuenta());
			result.setImporteCuota(cvf.getImporteCuota());
			result.setFondo(cvf.getFondo());
			result.setPresupuesto(cvf.getPresupuesto());
		} else {
			result = findOne(cvf.getComunidadId());
			Assert.notNull(result);

			result.setCif(cvf.getCif());
			result.setDireccion(cvf.getDireccion());
			result.setNumeroDeCuenta(cvf.getNumeroDeCuenta());
			result.setImporteCuota(cvf.getImporteCuota());
			result.setFondo(cvf.getFondo());
		}

		return result;

	}

	public Collection<ComunidadDeVecinos> findByVecino() {
		Collection<ComunidadDeVecinos> res;
		Vecino vecino;
		int vecinoId;

		vecino = vecinoService.findByPrincipal();
		vecinoId = vecino.getId();
		res = comunidadDeVecinosRepository.findByVecino(vecinoId);
		return res;
	}

	public Boolean isPresidente(int comunidadId) {
		ComunidadDeVecinos comunidad;
		Vecino principal;
		Boolean res;

		principal = vecinoService.findByPrincipal();
		comunidad = findOne(comunidadId);

		if (comunidad.getPresidente() == null) {
			res = false;
		} else {
			res = comunidad.getPresidente().equals(principal);
		}

		return res;

	}

	public Collection<String> findViviendasOcupadas(int comunidadId) {
		Collection<String> res;
		res = comunidadDeVecinosRepository.findViviendasOcupadas(comunidadId);
		return res;
	}
}
